package kgame5.k3d.util3d {
import kgame5.k3d.core.obj3d.info.geometry.GeometryInfo;
import kgame5.k3d.core.obj3d.info.material.MaterialInfo;
import kgame5.k3d.core.obj3d.node3d.Mesh3D;
import kgame5.k3d.core.obj3d.node3d.animator.Animator3D;
import kgame5.k3d.core.parser.MD2Parser;
import kgame5.k3d.util3d.loader3d.*;
import kgame5.kutil.*;

import flash.display.*;
import flash.events.*;
import flash.net.*;
import flash.utils.*;

/**
 * @author kangkai
 * 读取的外部模型初始化的时候读取，以后每次用就在这里来取
* 	1,分析问题,lib3d的职责是读取.obj文件并存储各个独立模型为data3d，并读取图片并存储
* 	builder根据制定的data3d和bmp来组装
* 	Lib3D里由名字和data3d和bmd一一对应
* 	
* 	提前把需要的东西都加载进来，这个方案很好
 */
public class Lib3D extends EventDispatcher{
	//全部加载完毕
	public static const 
		EVENTYTPE_LOAD_ALL_OK:String="EVENTYTPE_LOAD_ALL_OK",
		EVENTYTPE_LOAD_ITEM_OK:String="EVENTYTPE_LOAD_ITEM_OK";
	
	private  var dict:Dictionary;
	private  var idx:int;
	private  var aFileUrl:Array;//要加载的obj的文件地址,不能同时加载很多，否则解析的时候会堵塞的
	
	private var l_mesh:Loader3DObjX;
	private var l_skin:Loader3DSkin;
	private var l_x:URLLoader;//直接原因是加载xml用的,也可以加载txt
	private var l_md2:URLLoader;
	
	public function Start(p_aFileUrl:Array){
		trace2("Lib3D.Start启动加载模型");
		
		if(p_aFileUrl.length==0){//!!如果是空的就不加载了
			return;
		}
		
		dict=new Dictionary();
		aFileUrl=p_aFileUrl;
		idx=0;//idx开始是-1,因为loadNext是要加下一个的
		
		//下一步
		loadNext();
	}
	
	public function Clear(){
		dict=null;
	}
	
	private function loadSkin(sSkinUrl:String){
		trace2("Lib3D.loadSkin",sSkinUrl);
		l_skin=new Loader3DSkin();
		l_skin.addEventListener(Loader3DSkin.EVENTTYPE_LOADOK, onLoadSkinOK);
		l_skin.Load(sSkinUrl);
	}
	private function onLoadSkinOK(e:KEvent){
		trace2("Lib3D.onLoadSkinOK",aFileUrl[idx]);
		//trace2("加载皮肤到了，全替换皮肤");
		var bmd:BitmapData=e.info.bmd;
		
		var sFileUrl:String=aFileUrl[idx];
		dict[sFileUrl]=bmd;
		
		//下一步
		onLoadItemOK();
	}
	
	private  function loadObj(sFileUrl:String){
		trace2("Lib3D.loadObj",sFileUrl);
		l_mesh=new Loader3DObjX();
		l_mesh.addEventListener(Loader3DObjX.EVENTTYPE_ALL_MESH3D_LOADOK, onLoadObjOK);
		l_mesh.Load(sFileUrl);
	}
	private  function onLoadObjOK(e:KEvent){
		trace2("Lib3D.onLoadObjOK");
		//解析模型
		
		var sFileUrl:String=aFileUrl[idx];
		
		dict[sFileUrl]=l_mesh._firstMesh3D.gi;
		
		//下一步
		onLoadItemOK();
	}
	
	////////////==加载某种未知的文件
	private  function loadX(sFileUrl:String){
		trace2(this,"loadX",sFileUrl);
		l_x=new URLLoader();
		l_x.addEventListener(Event.COMPLETE, onLoadXOK);
		l_x.load(new URLRequest(sFileUrl));
	}
	private  function onLoadXOK(e:Event){
		trace2(this,"onLoadXOK",aFileUrl[idx]);
		
		var sFileUrl:String=aFileUrl[idx];
		
		dict[sFileUrl] = l_x.data;
		
		//下一步
		onLoadItemOK();
	}
	//////////
	
	//加载md2文件
	private  function loadMD2(sFileUrl:String):void{
		trace2(this,"loadMD2",sFileUrl);
		l_md2=new URLLoader();
		l_md2.addEventListener(Event.COMPLETE, onLoadMD2OK);
		l_md2.dataFormat=URLLoaderDataFormat.BINARY;
		l_md2.load(new URLRequest(sFileUrl));
	}
	private  function onLoadMD2OK(e:Event):void{
		trace2(this,"onLoadMD2OK",aFileUrl[idx]);
		
		var sFileUrl:String=aFileUrl[idx];
		
		dict[sFileUrl] = l_md2.data;
		
		//下一步
		onLoadItemOK();
	}
	
	//加载下一个
	private function loadNext(){
		trace2(this,"loadNext");
		
			var sFileUrl:String=aFileUrl[idx];
			
			var re_png:RegExp=/(\.png)/i;
			var re_jpg:RegExp=/(\.jpg)/i;
			var re_obj:RegExp=/(\.obj)/i;
			var re_md2:RegExp=/(\.md2)/i;
//			trace2("jpg?",re_jpg.test(sFileUrl));
//			trace2("png?",re_png.test(sFileUrl));
//			trace2("obj?",re_obj.test(sFileUrl));
			if(re_jpg.test(sFileUrl)||re_png.test(sFileUrl)){//是jpg或png文件
				loadSkin(sFileUrl);
			}else if(re_obj.test(sFileUrl)){//是obj文件
				loadObj(sFileUrl);
			}else if(re_md2.test(sFileUrl)){//是md2文件
				loadMD2(sFileUrl);
			}else{
				loadX(sFileUrl);
			}
		
	}
	private function onLoadItemOK(){
		
		this.dispatchEvent(new KEvent(EVENTYTPE_LOAD_ITEM_OK));
		
		if(idx==aFileUrl.length-1){//通知加载完毕
			this.dispatchEvent(new KEvent(EVENTYTPE_LOAD_ALL_OK));
		}else{//还没加载完
			
			idx++;
			loadNext();
		}
	}
	
	//返回加载进度
	public function getProgress():int{
		return (idx+1)/aFileUrl.length*100;
	}
	
	//根据名字取出内容
	 //* 1,var map_xml:XML=new XML(_lib3D_mapData.getData(NameX.getMapDataUrl(mapID)));
	//*  这个曾经花了很多时间做，原因是直接去的的这个不是xml，他只是个string,需要装换成xml
	public function getData(sName:String):Object{
		return dict[sName];
	}
	
	//!!严重注意，这个是clone后的data了
	public function getDataClone(sName:String):Object{
		var dd:Object=getData(sName);
		var ba:ByteArray=new ByteArray();
		ba.writeObject(dd);
		ba.position=0;
		return ba.readObject();
	}
	
	//取得一个Animator3D对象
	public function getAnimator3D(md2FileUrl:String,mtabFileUrl:String,skinFileUrl:String):Animator3D{
		var anim:Animator3D=null;
		
		//md2
		var md2Parser:MD2Parser=new MD2Parser(4);//注意这里的fps是无效的，就是随便写的一个
		md2Parser.parse(getDataClone(md2FileUrl) as ByteArray);
		anim=md2Parser.animator;
		
		//mtab
		if(mtabFileUrl==null||getData(mtabFileUrl)==null){
			anim.setupActionTableXML(null);
		}else{
			anim.setupActionTableXML(new XML(getData(mtabFileUrl) as String));
		}
		
		//skin
		var mi:MaterialInfo=new MaterialInfo();
		mi.bmd=(getData(skinFileUrl) as BitmapData).clone();
		anim.setMaterialInfo(mi);
		
		return anim;
	}
	
	//根据.obj的文件名字取出data3d
	public function getGeometryInfo(sFileUrl:String):GeometryInfo{
		return GeometryInfo(dict[sFileUrl]).clone();
	}
	//根据名字新生成一个md。因为是由data3d生成，速度很快，因为是享元模式啊
	public function getMesh3D(sFileUrl:String):Mesh3D{
		
		var gi:GeometryInfo=getGeometryInfo(sFileUrl);
		if(gi==null){
			throw new Error("getMesh3D找不到此sFileUrl:"+sFileUrl);
		}
		var mesh:Mesh3D=new Mesh3D();
		mesh.setGeometryInfo(gi);
		return mesh;
	}
	//根据obj名字和png名字返回一个已经贴了图的md
	public function getSkinedMesh3D(sMeshName:String,sSkinName:String):Mesh3D{
//		var md:Mesh3D=getMesh3D(sObjName);
//		
//		var bmd:BitmapData=this.getBmd(sSkinName);
//		//md.visu.setBmd(bmd);
//		md.mi.bmd=bmd;
//		md.forceRefresh();//这个很重要啊
//		
//		return md;
		
		return getAnimator3D(sMeshName,null,sSkinName);

	}
	//根据名字取得一个bmd
	public function getBmd(sFileUrl:String):BitmapData{
		return BitmapData(dict[sFileUrl]).clone();
	}
	
	///////////////////调试信息//////////////////
	private function trace2(...args){
		T.p(args);
	}
}//end of class
}
